﻿using System;
using System.Collections;
using DataScripter.Containers;
using DataScripter.Scripting.Output;
using DataScripter.Scripting.Output.Sql.SqlServer;
using DataScripter.Scripting.ProcessDefinitions;
using DataScripter.Sorters;

namespace DataScripter.Scripting
{
    public class Engine : IEngine
    {
        private readonly IContainer _iocContainer;

        public Engine()
        {
            Name = "Engine";
            _iocContainer = new WindsorContainer(Name);
            _iocContainer.RegisterType<IEngine>(this);
        }

        public string Name { get; private set; }

        public void Run()
        {
            if (_iocContainer.HasRegistration<IProcessDefinition>())
            {
                IProcessDefinition processDefinition = _iocContainer.Resolve<IProcessDefinition>();
                processDefinition.Run();
            }
            else
            {
                Script(new SqlServerScriptOptions(SqlScriptType.Insert) {ScriptOutputType = ScriptOutputType.File});
            }
        }

        public IScriptResult Script(ScriptOptions options)
        {
            if (!_iocContainer.HasRegistration<IFullControlOutputProducer>())
            {
                _iocContainer.RegisterType<IFullControlOutputProducer>(typeof(DefaultFullControlOutputProducer));
            }
            if (!_iocContainer.HasRegistration<ISorter<ITableScriptRequest>>())
            {
                _iocContainer.RegisterType<ISorter<ITableScriptRequest>>(typeof(TableScriptRequestSorterWithForeignKeysFirst));
            }
            IFullControlOutputProducer fullControlOutputProducer = _iocContainer.Resolve<IFullControlOutputProducer>();
            return fullControlOutputProducer.Script(options);
        }

        #region IContainer

        public bool HasRegistration<T>()
        {
            return _iocContainer.HasRegistration<T>();
        }

        public void RegisterType<T>(Type type)
        {
            _iocContainer.RegisterType<T>(type);
        }

        public void RegisterType<T>(string name, Type type)
        {
            _iocContainer.RegisterType<T>(name, type);
        }

        public void RegisterType(string name, Type type, Type interfaceType)
        {
            _iocContainer.RegisterType(name, type, interfaceType);
        }

        public T Resolve<T>()
        {
            return _iocContainer.Resolve<T>();
        }

        public T Resolve<T>(string name)
        {
            return _iocContainer.Resolve<T>(name);
        }

        public void RegisterType<T>(T instance)
        {
            _iocContainer.RegisterType(instance);
        }

        public void RegisterType<T>(string name, T instance)
        {
            _iocContainer.RegisterType(name, instance);
        }

        public IContainer CreateChildContainer(string name)
        {
            return _iocContainer.CreateChildContainer(name);
        }

        public bool HasRegistration<T>(string name)
        {
            return _iocContainer.HasRegistration<T>(name);
        }

        public T Resolve<T>(string name, IDictionary dictionary)
        {
            return _iocContainer.Resolve<T>(name, dictionary);
        }

        #endregion
    }
}